Fix xenstored watch crash.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 14 Sep 2005 08:41:49 +0000 (08:41 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 14 Sep 2005 08:41:49 +0000 (08:41 +0000)
When a connection blocked waiting on a transaction, don't queue watch events.
Sure, they'd be ignored and re-transmitted, but it hits an assert that we don't
send data out blocked connections, and it's wasteful.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (authored)
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
tools/xenstore/testsuite/16block-watch-crash.test [new file with mode: 0644]
tools/xenstore/xenstored_watch.c
tools/xenstore/xs_test.c

diff --git a/tools/xenstore/testsuite/16block-watch-crash.test b/tools/xenstore/testsuite/16block-watch-crash.test
new file mode 100644 (file)
index 0000000..564f6d3
--- /dev/null
@@ -0,0 +1,13 @@
+# Test case where blocked connection gets sent watch.
+
+mkdir /test
+watch /test token
+1 start /test
+# This will block on above
+noackwrite /test/entry create contents
+1 write /test/entry2 create contents
+1 commit
+readack
+expect /test/entry2:token
+waitwatch
+ackwatch token
index e40318ee2f587db565024f39c9fcacac7e8e4a95..a543f8a4952e9a5e381b788348c5bdd4402baea7 100644 (file)
@@ -144,7 +144,7 @@ void fire_watches(struct connection *conn, const char *node, bool recurse)
                        else
                                continue;
                        /* If connection not doing anything, queue this. */
-                       if (!i->out)
+                       if (i->state == OK)
                                queue_next_event(i);
                }
        }
index 58445b9f25502b4cc690acaaccd9ee0590780294..6f4d0d5bc44219dadd676abf015942fbcd47eeb6 100644 (file)
@@ -398,12 +398,16 @@ static void do_noackwrite(unsigned int handle,
 static void do_readack(unsigned int handle)
 {
        enum xsd_sockmsg_type type;
-       char *ret;
-
-       ret = read_reply(handles[handle]->fd, &type, NULL);
-       if (!ret)
-               failed(handle);
-       free(ret);
+       char *ret = NULL;
+
+       /* Watches can have fired before reply comes: daemon detects
+        * and re-transmits, so we can ignore this. */
+       do {
+               free(ret);
+               ret = read_reply(handles[handle]->fd, &type, NULL);
+               if (!ret)
+                       failed(handle);
+       } while (type == XS_WATCH_EVENT);
 }
 
 static void do_setid(unsigned int handle, char *id)